#-*- coding: UTF-8 -*-
import sys, os, re
import gzip
import lzma as xz

def usage():
	print(r'''
1.  help message
	$ md5_snap.py {-i input_md5} {-o output_md5} {-e export_diff} <dir>

2. create MD5sum of all files @<dir>
	$ md5_snap.py <dir> -o md5.gz

3. find all diff files @<dir> to export.rar
	$ md5_snap.py <dir> -i <md5.gz> -e export.tar.gz
	$ md5_snap.py -i tsinghua_20250111.md5.gz \
	-e tsinghua_20250212_diff.tar.gz -o tsinghua_20250212.md5.gz \
	mirrors.tuna.tsinghua.edu.cn/
	''')
	exit(0)

def md5_input(fn_i):
	try: 
		if re.search(r'\.gz$', fn_i):
			fp = gzip.open(fn_i, 'rt')
		elif re.search(r'\.xz$', fn_i):
			fp = xz.open(fn_i, 'rt')
		else:
			fp = open(fn_i, 'r') 
	except Exception as e: 
		print(e)
		exit(OSError(e).errno)
	
	md5 = {}
	while line := fp.readline():
	#b95d850859c7e2e.. ubuntu-ports/dists/jammy-proposed/main/i18n/Translation-en_GB.gz
		if not (m:=re.search(r'(\S+)\s+(\S+)', line)): 
			continue
		md5[m[2]]=m[1]
	return md5
## md5_input

if __name__ == '__main__':
	if len(sys.argv)==0:
		usage()
	if '-i' in sys.argv:
		i = sys.argv.index('-i')
		if len(sys.argv)<(i+1): usage()
		fn_i=sys.argv[i+1]
		del(sys.argv[i:i+2])
	else: fn_i=None
	if '-o' in sys.argv:
		i = sys.argv.index('-o')
		if len(sys.argv)<(i+1): usage()
		fn_o=sys.argv[i+1]
		del(sys.argv[i:i+2])
	else: fn_o=None

	if '-e' in sys.argv:
		i = sys.argv.index('-e')
		if len(sys.argv)<(i+1): usage()
		fn_e=sys.argv[i+1]
		del(sys.argv[i:i+2])
	else: fn_e=None

	if len(sys.argv)<2: usage()
	d = os.path.normpath(sys.argv[1])
	#esc_d=re.escape(d)
	esc_d=re.sub('/', '\\/', re.escape(d))
	if not os.path.isdir(d): usage()

	if not (fn_i or fn_e):
	# create md5sum output
		if fn_o: 
			os.system(f'find {d} -type f|xargs md5sum|sed "s/{esc_d}\\///"|gzip >{fn_o}')
		else:
			os.system(f'find {d} -type f|xargs md5sum|sed "s/{esc_d}\\///"')
		exit()
	# fn_i=None

	if fn_e == None: usage()

	if fn_i: md5 = md5_input(fn_i)
	else: md5 = {}

	gz = os.popen(f'tar -C {d} -czf {fn_e} -T- 2>/dev/null 1>&2', mode='w')

	if fn_o:
		try: 
			if re.search(r'\.gz$', fn_o):
				fn_o = gzip.open(fn_o, 'wt')
			elif re.search(r'\.xz$', fn_o):
				fn_o = xz.open(fn_o, 'wt')
			else:
				fn_o = open(fn_o, 'w') 
		except Exception as e: 
			print(e)
			exit(OSError(e).errno)
	## if fn_o:

	cmd=f"find {d} -type f|xargs md5sum|sed 's/{esc_d}\\///'"
	#print(cmd)
	with os.popen(cmd) as ff:
		while ll:=ff.readline():
			if not (m:=re.search(r'(\S+)\s+(\S+)', ll)): 
				continue

			if not fn_o: print(m[1], m[2])
			else: fn_o.write(f'{m[1]} {m[2]}\n')

			if m[2] in md5 and md5[m[2]]==m[1]:
				continue
			print(m[2], file=gz)
		## while(readline)
	gz.close()
	if fn_o: fn_o.close()
